#include "networkzingmewebsocket.h"
#include "network/networkconnectionrequest.h"
#include "QtWebSockets/QWebSocket"
#include <QTimer>

namespace Network {

namespace Zingme {

WebSocket::WebSocket(QObject *parent)
    : QObject(parent)
    , m_socket(NULL)
    , m_pingTimer(NULL)
{

}


void WebSocket::connect(const QString &url, unsigned int port, const QVariant &params)
{
    QVariantMap map = params.toMap();
    QString resource;
    if (map.size() > 0) {
        for (QVariantMap::ConstIterator iterator = map.begin();
             iterator != map.end();
             iterator++) {
            if (resource.length() == 0)
                resource = QString("%1=%2").arg(iterator.key(),
                                                (*iterator).toString());
            else
                resource += QString("&%1=%2").arg(iterator.key(),
                                                  (*iterator).toString());
        }
    }

    if (resource.length() > 0)
        resource = "/?" + resource;

    m_socket = new QWebSocket(QString("wsengine-qt"), QWebSocketProtocol::VersionLatest, this);//Tufao::WebSocket(this);

//    m_socket->setMessagesType(Tufao::WebSocket::TEXT_MESSAGE);
    QObject::connect(m_socket,
                     &QWebSocket::connected,
                     this,
                     &WebSocket::onConnected);

    QObject::connect(m_socket,
                     &QWebSocket::binaryMessageReceived,
                     this,
                     &WebSocket::onReceived);

    QObject::connect(m_socket,
                     &QWebSocket::textMessageReceived,
                     this,
                     &WebSocket::onReceivedTextMessage);

    QObject::connect(m_socket,
                     SIGNAL(error(QAbstractSocket::SocketError)),
                     this,
                     SLOT(onSocketError(QAbstractSocket::SocketError)) );

    QObject::connect(m_socket,
                     &QWebSocket::disconnected,
                     this,
                     &WebSocket::onDisconnected);

    QObject::connect(m_socket,
                     &QWebSocket::pong,
                     this,
                     &WebSocket::onPong);

    qDebug() << tr("connecting to ")+ "ws://"+url+":" + QString("%1").arg(port)+resource;
    m_socket->open(QUrl("ws://"+url+":" + QString("%1").arg(port)+resource) );

}


void WebSocket::onSocketError(QAbstractSocket::SocketError){
    if (m_socket == NULL)
        return;

    qDebug()<<"socket Error " <<m_socket->errorString()<<endl;
}

void WebSocket::send(ConnectionRequest *request)
{
    if (m_socket == NULL)
        return;

    QByteArray message = request->content();

    m_socket->sendTextMessage(QString::fromUtf8(message));
    m_socket->flush();
}


void WebSocket::disconnect()
{
    if (m_socket == NULL)
        return;
    m_socket->close();
}


bool WebSocket::isConnected() const
{
    if (m_socket == NULL)
        return false;

    return m_socket->isValid();
//    return m_socket->isConnected();
}


void WebSocket::onConnected()
{
    if (m_socket == NULL)
        return;

    qDebug() << "onConnected\n";
//    if (m_pingTimer == NULL)
//    {
//        m_pingTimer = new QTimer(this);
//    }

//    m_pingTimer->stop();

//    QObject::disconnect(m_pingTimer,
//                     &QTimer::timeout,
//                     this,
//                     &WebSocket::sendPing
//                     );

//    QObject::connect(m_pingTimer,
//                     &QTimer::timeout,
//                     this,
//                     &WebSocket::sendPing
//                     );
//    m_pingTimer->setSingleShot(false);
//    m_pingTimer->setInterval(2000);
//    m_pingTimer->start();
    emit connected();
}

void WebSocket::sendPing(){

    if (m_socket == NULL)
        return;
    qDebug() << "send ping " ;
    //Todo: check lai server
    m_socket->ping();
}

void WebSocket::onPong(quint64 elapsedTime, const QByteArray &payload)
{
    qDebug()<<"onPong "<<elapsedTime<< " " <<payload;
}

void WebSocket::onReceived(QByteArray message)
{
    if (m_socket == NULL)
        return;

    // qDebug() << "received: " << QString(message);
    emit received(message);
}

void WebSocket::onReceivedTextMessage(QString message)
{
    if (m_socket == NULL)
        return;
    emit received(message.toUtf8() );
}

void WebSocket::onDisconnected()
{
    if (m_socket == NULL)
        return;
    qDebug()<<"WebSocket onDisconnected";
    m_socket->close();
    m_socket->deleteLater();
    m_socket = NULL;
    emit this->disconnected();

}

} // namespace zingme

} // namespace network
